winsafe\user\handles/
haccel.rs

1#![allow(non_camel_case_types, non_snake_case)]
2
3use crate::decl::*;
4use crate::guard::*;
5use crate::kernel::privs::*;
6use crate::user::ffi;
7
8handle! { HACCEL;
9	/// Handle to an
10	/// [accelerator table](https://learn.microsoft.com/en-us/windows/win32/winprog/windows-data-types#haccel).
11}
12
13impl HACCEL {
14	/// [`CreateAcceleratorTable`](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-createacceleratortablew)
15	/// function.
16	#[must_use]
17	pub fn CreateAcceleratorTable(accel: &[ACCEL]) -> SysResult<DestroyAcceleratorTableGuard> {
18		// For some reason, debug builds were randomly crashing with error 998:
19		// Invalid access to memory location.
20		// So, allocate an HGLOBAL buffer and copy the ACCEL array onto it.
21		let hg_buf = HGLOBAL::GlobalAlloc(
22			crate::co::GMEM::ZEROINIT,
23			std::mem::size_of::<ACCEL>() * accel.len(),
24		)?;
25		{
26			let sli =
27				unsafe { std::slice::from_raw_parts_mut(hg_buf.ptr() as *mut ACCEL, accel.len()) };
28			sli.iter_mut()
29				.zip(accel.iter())
30				.for_each(|(buf2, src)| *buf2 = *src);
31		}
32
33		unsafe {
34			ptr_to_sysresult_handle(ffi::CreateAcceleratorTableW(hg_buf.ptr(), accel.len() as _))
35				.map(|h| DestroyAcceleratorTableGuard::new(h))
36		}
37	}
38}